export default class NewWebSocket {
    constructor(url = "ws://localhost:9000", options = {}, handleMessage = (data) => {console.log(data)}) {
		this.options = options
		this.messageMap = {} 
		this.subscribeMap = []
		this.waitSubMap = []
		this.repeatCount = 0 // 重新连接花费的次数，open事件触发后重置为0
        this.lockReconnect = false //避免重复连接
		this.socket = null //websocket的实例
		this.url = url // websocket地址
        this.messageList = [] // 服务端推送数据做缓存，防止渲染频繁
        this.closeType = 'client' //是否客服端主动断开链接 normol 服务端断开链接 client 客服端主动断开链接
        this.binaryType = options.binaryType || 'arraybuffer'
        this.randerTime = options.randerTime || 1 * 1000 // 数据需要快速渲染可适当调小
        this.timeout = options.timeout || 15 * 1000, //心跳检测间隔15秒
        this.reconnectTime = options.reconnectTime || 5 * 1000, // 重连间隔
        this.reconnectTimeOut = options.reconnectTimeOut || 10 * 1000, // 心跳检测多久没响应则重连
        this.timeoutObj = null, // 心跳检测定时器
        this.reconnectTimer = null, // 重连定时器
        this.timeoutReconnectTimer = null , // 断开重连定时器
        this.handleMessage = handleMessage
		this.init()
    }
    async init() {
        if (this.socket) {
			this.socket.onopen = this.socket.onclose = this.socket.onmessage = this.socket.onerror = null
		}
        console.log('----初始化socket----')
        // 初始化默认为需要服务端主动断开, 前端主动断开则为normal
        this.resetTimeOut()
		//生成websocket对象
		const BrowserWebSocket = window.WebSocket || window.MozWebSocket
        // console.log('----new hoowebsocket---');
		const socket = new BrowserWebSocket(this.url)
		//socket属性
		socket.binaryType = this.binaryType
		socket.onopen = (event) => this.onOpen(event)
		socket.onclose = (event) => this.onClose(event)
		socket.onmessage = (event) => this.onMessage(event.data)
		socket.onerror = (err) => this.onError(err)
		this.socket = socket
    }
    onOpen(event) {
        console.log('----连接已建立----')
        console.log('openEvent:', event)
        // 订阅socket,开始心跳检测或者socket鉴权
        this.repeatCount = 0
        console.log('----建立连接第一次发送心跳检测----')
        this.socket.send('心跳测试')
        this.emit('open') // 触发open事件
        this.heartCheckStart()
    }
    onClose(event) {
        console.log('----连接已断开----')
        console.log('closeEvent:', event)
        console.log('type', this.closeType)
        if(this.closeType == 'normol') {
            // 关闭socket处理
        } else {
            // 其他原因或者服务器主动断开
            this.reconnect()
        }
    }
    onMessage(event) {
        console.log('----服务端响应数据----')
        console.log('messageEvent:', event)
        this.messageList.push(event)
        if(!this.messageTimer) {
            this.messageTimer = setTimeout(() => {
            this.messageList.map((item) => {
                this.handleMessage(item)
            })
            clearTimeout(this.messageTimer)
            this.messageList = []
            this.messageTimer = null
            }, this.randerTime)
        }
        this.heartCheckStart()
        try {
			const data = typeof event == "string" ? event : JSON.parse(event)
			this.onReceiver({
				type: "message",
				data: data,
			});
		} catch (err) {
            console.log('messageErr:', err)
        }
    }
    onError(err) {
        console.log('onError', err);
        this.reconnect();
    }
    on(name, handler) {
        // 存储相应订阅后的回调
		this.messageMap[name] = handler;
	}
    emit(name) {
        // 存储相应订阅后的回调
		let callback = this.messageMap[name]
        callback && callback()
	}
    onReceiver(data) {
		console.log(data) //根据data返回的类型作出不同相应
		// const callback = this.messageMap[data.type];
		// if (callback) callback(data);
	}
    subscribe(data, callbackName, callback) {
		this.joinSubscribeMap(data);
		this.sendMessage(data);
		this.on(callbackName, callback);
	}
	unsubscribe(data) {
		this.deleteSubscribeMap(data);
		this.sendMessage(data);
	}
    joinSubscribeMap(data) {
		let subType = data.type
		let hasTopic = false
		this.subscribeMap.forEach((item) => {
			if (item.type == subType) {
				hasTopic = true
                return null
			}
		})
		if (!hasTopic) {
			this.subscribeMap.push(data);
		}
	}
	deleteSubscribeMap(data) {
		let subType = data.type
		this.subscribeMap.forEach((item, index) => {
			if (item.type == subType) {
				this.subscribeMap.splice(index, 1)
                return null
			}
		})
	}
    joinWaitSubscribeMap(data) {
		let subType = data.type
		let hasTopic = false
		this.waitSubMap.forEach((item) => {
			if (item.type == subType) {
				hasTopic = true
                return null
			}
		})
		if (!hasTopic) {
			this.waitSubMap.push(data);
		}
	}
    deleteWaitSubscribeMap(data) {
		let subType = data.type
		this.waitSubMap.forEach((item, index) => {
			if (item.type == subType) {
				this.waitSubMap.splice(index, 1);
                return null
			}
		});
	}
    sendMessage(data) {
		let that = this
        const sendData = typeof data == 'string' ? data : JSON.stringify(data)
        console.log('readyState:', this.socket.readyState )
		if (this.socket.readyState == WebSocket.OPEN) {
			this.socket.send(sendData)
            this.deleteWaitSubscribeMap(data)
		} else {
			this.joinWaitSubscribeMap(data);
			this.on("open", () => {
				that.waitSubMap.forEach((item) => {
					that.sendMessage(item)
				});
			});
		}
	}
    // 主动断开socket
    close() {
        if(!this.socket) return
        this.closeType = 'normol'
        this.socket.close()
        this.messageMap = {}
		this.waitSubMap = []
		this.socket = null
        this.timeoutObj && clearTimeout(this.timeoutObj)
        this.reconnectTimer && clearTimeout(this.reconnectTimer)
        this.timeoutReconnectTimer && clearTimeout(this.timeoutReconnectTimer)
        this.timeoutObj = null
        this.reconnectTimer = null 
        this.timeoutReconnectTimer = null 
    }
    reconnect() {
        console.log('----重新连接----')
        let self = this
        if (this.lockReconnect) return
        this.lockReconnect = true
        // 没连接上会一直重连，设置延迟避免请求过多
        this.reconnectTimer && clearTimeout(this.reconnectTimer)
        this.reconnectTimer = setTimeout(function() {
            self.init()
            self.lockReconnect = false
            self.repeatCount++
            console.log(`--重连次数：${self.repeatCount}--`)
            self.reconnect()
        }, this.reconnectTime)
    }
    // 开始心跳检测
    heartCheckStart() {
        var self = this
        clearTimeout(this.timeoutObj)
        clearTimeout(this.reconnectTimer)
        clearTimeout(this.timeoutReconnectTimer)
        this.timeoutObj = null 
        this.reconnectTimer = null
        this.timeoutReconnectTimer = null
         //onmessage拿到返回的心跳就说明连接正常
         //这里发送一个心跳，后端收到后，返回一个心跳消息，
        this.timeoutObj = setTimeout(() => {
            console.log('----发送心跳检测two----')
            self.socket.send("心跳测试")
            self.timeoutReconnectTimer = setTimeout(() => {
                self.reconnect()         
            }, self.reconnectTimeOut)
        }, this.timeout)
    }
    resetTimeOut() {
        this.closeType = 'client'
        this.timeoutObj && clearTimeout(this.timeoutObj)
        this.reconnectTimer && clearTimeout(this.reconnectTimer)
        this.timeoutReconnectTimer && clearTimeout(this.timeoutReconnectTimer)
        this.timeoutObj = null
        this.reconnectTimer = null
        this.timeoutReconnectTimer = null
    }
}